home *** CD-ROM | disk | FTP | other *** search
- #if defined(UseDumpFiles)
-
- #include "DumpHeader.h"
-
- #else
-
- #include <Drag.h>
- #include <Errors.h>
- #include <GestaltEqu.h>
-
- #endif
-
- #include "ListCode.h"
- #include "DragSupport.h"
-
- DragHandlerGlobals pDragGlobals;
-
-
-
- /*-----------------------------------------------------------------*/
- Boolean DragMgrPresent(void)
- {
- OSErr err;
- long response = 0L;
-
- err = Gestalt(gestaltDragMgrAttr, &response);
-
- if ((err == noErr)
- && (response && (1 << gestaltDragMgrPresent) != 0))
- return true;
-
- else
- return false;
- }
-
-
- /*-----------------------------------------------------------------
-
- InstallDragHandlers attaches my tracking and receive handlers to
- one of the application's windows
-
- */
- OSErr InstallDragHandlers(WindowPtr theWindow)
- {
- OSErr err;
-
- if (DragMgrPresent()) {
- err = InstallTrackingHandler(DragTracker, theWindow, nil);
-
- if (err == noErr) {
- err = InstallReceiveHandler(DragReceiver, theWindow, nil);
-
- if (err != noErr)
- (void) RemoveTrackingHandler(DragTracker, theWindow);
- }
- }
- if (err != noErr) Debugger();
-
- return err;
- }
-
-
- /*-----------------------------------------------------------------
-
- RemoveDragHandlers removes my tracking and receive handlers from
- one of the application's windows (prior to the window's disposal,
- presumably)
-
- */
- void RemoveDragHandlers(WindowPtr theWindow)
- {
- if (DragMgrPresent()) {
- RemoveReceiveHandler(DragReceiver, theWindow);
- RemoveTrackingHandler(DragTracker, theWindow);
- }
- }
-
-
- /*-----------------------------------------------------------------
-
- DragItemsAreAcceptable returns true if the contents (data) of
- the drag are and HFS flavor
-
- DragItemsAreAcceptable is called by the tracking and
- receive handlers
-
- */
- Boolean DragItemsAreAcceptable(DragReference theDrag)
- {
- OSErr err;
- unsigned short totalItems;
- ItemReference itemRef;
- Boolean acceptIt;
- OSType currOSType;
- Size flavorDataSize;
-
- acceptIt = false;
-
- // this app can only accept the drag of a single item
- err = CountDragItems(theDrag, &totalItems);
-
- if (err == noErr && totalItems == 1) {
- // get the reference number of the dragged item
- err = GetDragItemReferenceNumber(theDrag, 1, &itemRef);
-
- if (err == noErr) {
- // check if the item is from the Finder
- flavorDataSize = sizeof(OSType);
- err = GetFlavorData(theDrag, itemRef, myPersonalFlavorType, &currOSType,
- &flavorDataSize, 0);
-
- if (err == noErr)
- acceptIt = true;
- }
- }
- return acceptIt;
- }
-
-
- /*-----------------------------------------------------------------
-
- DragIsNotInSourceWindow returns true if the drag in progress
- is not in the same window it originated in
-
- DragIsNotInSourceWindow is called by the tracking and receive handlers
-
- Note that, if this application allowed items to be dragged within
- its windows, this function would not be appropriate.
- Instead, hilighting would probably occur in the source window
- when the dragHasLeftSourceWindow flag is set, and the receive
- handler wouldn't check this at all
-
- */
- Boolean DragIsNotInSourceWindow(DragReference theDrag)
- {
- DragAttributes currDragFlags;
-
- (void) GetDragAttributes(theDrag, &currDragFlags);
- return ((currDragFlags & dragInsideSenderWindow) == 0);
- }
-
-
- /*-----------------------------------------------------------------
-
- DragTracker is called by the drag manager whenever a drag is
- over one of the application's windows
-
- upon entry, the current port has been set to theWindow by the Drag Manager
-
- */
- pascal OSErr DragTracker(DragTrackingMessage theMessage, WindowPtr theWindow,
- void *handlerRefCon, DragReference theDrag)
- {
- #pragma unused (theWindow, handlerRefCon)
-
- RgnHandle tempRgn;
- Boolean mouseInList;
- OSErr err;
-
- err = noErr;
-
- switch (theMessage) {
-
- case dragTrackingEnterHandler:
-
- //
- // Any initialization for this window handler.
- //
- pDragGlobals.acceptableDragFlag =
- DragItemsAreAcceptable(theDrag);
- pDragGlobals.hilitedList = false;
-
- // let the drag manager know if we can't accept this drag
- if (!pDragGlobals.acceptableDragFlag)
- err = dragNotAcceptedErr;
- break;
-
- case dragTrackingEnterWindow:
- case dragTrackingInWindow:
- case dragTrackingLeaveWindow:
-
- //
- // Highlighting of the window during a drag is done
- // here. Do it only if we can accept these items
- // and we're not in the source window...
- //
-
- if (pDragGlobals.acceptableDragFlag) {
- //
- // Unless the mouse is leaving the visible area of the
- // window, check if it's in the window's content region
- //
-
- if (theMessage == dragTrackingLeaveWindow)
- mouseInList = false;
-
- else {
- Point localPt;
-
- (void) GetDragMouse(theDrag, &localPt, 0L);
- GlobalToLocal(&localPt);
- mouseInList = PtInDestList(localPt);
- }
-
- //
- // If the mouse is in the list
- //
-
- if ((mouseInList == true)
- && (pDragGlobals.hilitedList == false)) {
- Rect nuSpaceRect;
-
- GetDestListRect(&nuSpaceRect);
-
- tempRgn = NewRgn();
- RectRgn(tempRgn, &nuSpaceRect);
-
- // draw the hilight
- if (ShowDragHilite(theDrag, tempRgn, true) == noErr)
- // remember where hilighting is on
- pDragGlobals.hilitedList = mouseInList;
-
- DisposeRgn(tempRgn);
- }
-
- //
- // else if the mouse is not in the content region
- // and the window is hilighted, erase the hilight
- //
-
- else if ((mouseInList == false)
- && (pDragGlobals.hilitedList == true))
- if (HideDragHilite(theDrag) == noErr)
- // remember that nothing is hilited
- pDragGlobals.hilitedList = false;
-
- }
- break;
-
- // do nothing for the leaveHandler message
- case dragTrackingLeaveHandler:
- break;
-
- // let the drag manager know if we didn't recognize the message
- default:
- err = paramErr;
- }
-
- return err;
- }
-
-
- /*-----------------------------------------------------------------
-
- DragReceiver is called by the drag manager whenever a drag is
- ends on one of the application's windows
-
- */
- pascal OSErr DragReceiver(WindowPtr theWindow, void *handlerRefCon,
- DragReference theDrag)
- {
- #pragma unused (theWindow, handlerRefCon)
- ItemReference itemRef;
- Size dataSize;
- OSType theOSType;
- OSErr err = noErr;
- unsigned short numItems, counter;
-
- if (!DragItemsAreAcceptable(theDrag) || (pDragGlobals.hilitedList == false))
- return dragNotAcceptedErr;
-
- CountDragItems(theDrag, &numItems);
-
- for (counter = 1; counter <= numItems; counter++) {
- err = GetDragItemReferenceNumber(theDrag, counter, &itemRef);
- if (err != noErr) goto BailOut;
-
- dataSize = sizeof(OSType);
- err = GetFlavorData(theDrag, itemRef, myPersonalFlavorType, &theOSType, &dataSize, 0);
-
- //
- // OK, we're going to first remove the drag hilite from here, because
- // not doing so would result in a cleared out list rect, and when
- // we go through the trackingLeaveWindow message up above, the
- // HideDragHilite() call would draw the border again (since it's drawn
- // in XOr mode).
- //
-
- if (pDragGlobals.hilitedList == true) {
- if (HideDragHilite(theDrag) == noErr)
- // remember that nothing is hilited
- pDragGlobals.hilitedList = false;
- }
- AddToDestList(theOSType);
- }
-
- BailOut:
- return err;
- NoDragProcess:
- return dragNotAcceptedErr;
- }
-